#pragma once
/* Copyright (C) 2009 Vlad Roubtsov. All rights reserved. */

#include <string>

#include <boost/ptr_container/ptr_vector.hpp>
using boost::ptr_vector;
#include <boost/unordered_map.hpp>
using boost::unordered_map;

#include "vr/deject/component.hpp"
#include "vr/deject/factory/dependency.hpp"
#include "vr/util/utility.hpp"

#include "vr/deject/factory/adaptors.hpp" // [special include position]

//----------------------------------------------------------------------------

#define VR_REGISTER_WITH_FACTORY(cls, ac) \
    friend class ::vr::deject::component< cls >;\
    \
    static inline bool register_class ()\
    {\
        return ::vr::deject::factory::component_factory::register_adaptor (::vr::utility::as_class_name (typeid ( cls ).name ()), & ::vr::deject::factory::constructor_adaptor< cls , ac >::create);\
    }

namespace vr
{
namespace deject
{
namespace factory
{

class component_factory
{
    public: // ...............................................................

        typedef component_base * creator_t (const deject::component_id_type & ID, const ptr_vector<dependency> & deps);

        static component_base * create (const std::string & implID, const deject::component_id_type & ID, const ptr_vector<dependency> & deps);
        static bool register_adaptor (const std::string & implID, creator_t * creator);

    private: // ..............................................................

        typedef unordered_map<std::string, creator_t *> creator_map;


        component_factory (); // non-instantiable

        static creator_map & singleton ();

}; // end of class

} // end of 'factory'
} // end of 'deject'
} // end of namespace
//----------------------------------------------------------------------------
